import sys
import requests
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget, QTabWidget, QVBoxLayout,
    QHBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox,
    QComboBox, QDateEdit, QSpinBox, QTableWidget, QTableWidgetItem,
    QAbstractItemView, QHeaderView
)
from PyQt5.QtCore import QDate, Qt
from requests.exceptions import RequestException

API_URL = 'http://127.0.0.1:5000/api'


class CardKeyClient(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('卡密生成系统')
        self.resize(900, 600)

        # 类型映射
        self.type_map = {'时间卡密': 'time', '次数卡密': 'count'}
        self.type_map_rev = {'': '', 'time': '时间卡密', 'count': '次数卡密'}
        self.status_list = ['', '未激活', '已激活', '已过期', '次数用完']

        tabs = QTabWidget()
        tabs.addTab(self.generate_tab_ui(), '生成卡密')
        self.list_tab = self.list_tab_ui()
        tabs.addTab(self.list_tab_ui(), '卡密列表')
        tabs.currentChanged.connect(self.on_tab_changed)

        self.setCentralWidget(tabs)

    def generate_tab_ui(self):
        widget = QWidget()
        layout = QVBoxLayout()

        param_layout = QHBoxLayout()
        param_layout.addWidget(QLabel('数量:'))
        self.count_spin = QSpinBox()
        self.count_spin.setRange(1, 1000)
        param_layout.addWidget(self.count_spin)

        param_layout.addWidget(QLabel('类型:'))
        self.type_combo = QComboBox()
        self.type_combo.addItems(list(self.type_map.keys()))
        self.type_combo.currentTextChanged.connect(self.on_type_changed)
        param_layout.addWidget(self.type_combo)

        self.date_edit = QDateEdit(calendarPopup=True);
        self.date_edit.setDate(QDate.currentDate())
        param_layout.addWidget(QLabel('过期日期:'))
        param_layout.addWidget(self.date_edit)

        self.maxuses_spin = QSpinBox()
        self.maxuses_spin.setRange(1, 100000)
        param_layout.addWidget(QLabel('最大使用次数:'))
        param_layout.addWidget(self.maxuses_spin)

        layout.addLayout(param_layout)

        self.generate_btn = QPushButton('生成卡密');
        self.generate_btn.clicked.connect(self.generate_cards)
        layout.addWidget(self.generate_btn)

        self.result_edit = QLineEdit()
        self.result_edit.setReadOnly(True)
        layout.addWidget(self.result_edit)

        widget.setLayout(layout)
        self.on_type_changed(self.type_combo.currentText())
        return widget

    def on_type_changed(self, text):
        if self.type_map[text] == 'time':
            self.date_edit.setEnabled(True)
            self.maxuses_spin.setEnabled(False)
        else:
            self.date_edit.setEnabled(False)
            self.maxuses_spin.setEnabled(True)

    def generate_cards(self):
        data = {'count': self.count_spin.value(), 'card_type': self.type_map[self.type_combo.currentText()]}
        if data['card_type'] == 'time':
            data['expire_date'] = self.date_edit.date().toString('yyyy-MM-dd')
        else:
            data['max_uses'] = self.maxuses_spin.value()
        try:
            resp = requests.post(f"{API_URL}/generate", json=data, timeout=5)
            result = resp.json()
            if result.get('success'):
                self.result_edit.setText(','.join(result.get('card_keys', [])))
            else:
                QMessageBox.warning(self, '错误', result.get('message', '生成失败'))
        except RequestException:
            QMessageBox.critical(self, '网络异常', '网络异常，请检查网络连接。')
        except Exception as e:
            QMessageBox.critical(self, '异常', str(e))

    def list_tab_ui(self):
        widget = QWidget()
        main_layout = QVBoxLayout()

        # 搜索与操作放到顶部
        ctrl_layout = QHBoxLayout()
        ctrl_layout.addWidget(QLabel('卡密:'))
        self.key_search = QLineEdit()
        ctrl_layout.addWidget(self.key_search)
        ctrl_layout.addWidget(QLabel('状态:'))
        self.status_combo = QComboBox()
        self.status_combo.addItems(self.status_list)
        ctrl_layout.addWidget(self.status_combo)
        ctrl_layout.addWidget(QLabel('类型:'))
        self.type_search = QComboBox()
        self.type_search.addItems(list(self.type_map_rev.values()))
        ctrl_layout.addWidget(self.type_search)
        self.search_btn = QPushButton('搜索')
        self.search_btn.clicked.connect(self.on_search)
        ctrl_layout.addWidget(self.search_btn)
        self.activate_btn = QPushButton('激活选中')
        self.activate_btn.clicked.connect(self.activate_selected)
        ctrl_layout.addWidget(self.activate_btn)
        self.delete_btn = QPushButton('删除选中')
        self.delete_btn.clicked.connect(self.delete_selected)
        ctrl_layout.addWidget(self.delete_btn)
        main_layout.addLayout(ctrl_layout)

        # 表格
        self.table = QTableWidget();
        self.table.setColumnCount(8)
        self.table.setHorizontalHeaderLabels(['卡密', '类型', '状态', '生成时间', '激活时间', '过期时间', '已用次数', '总使用次数'])
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.MultiSelection)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.cellDoubleClicked.connect(self.show_cell_detail)
        main_layout.addWidget(self.table)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # 分页信息与总数放到底部
        bottom_layout = QHBoxLayout()
        self.total_lbl = QLabel('总数: 0')
        bottom_layout.addWidget(self.total_lbl)
        bottom_layout.addStretch()
        self.prev_btn = QPushButton('上一页')
        self.prev_btn.clicked.connect(self.prev_page)
        bottom_layout.addWidget(self.prev_btn)
        self.page_lbl = QLabel('第1/1页')
        bottom_layout.addWidget(self.page_lbl)
        self.next_btn = QPushButton('下一页')
        self.next_btn.clicked.connect(self.next_page)
        bottom_layout.addWidget(self.next_btn)
        main_layout.addLayout(bottom_layout)

        self.current_page = 1
        self.total_pages = 1
        self.load_list()

        widget.setLayout(main_layout)
        return widget

    def build_params(self):
        params = {'page': self.current_page, 'per_page': 20}
        if self.key_search.text().strip(): params['keyword'] = self.key_search.text().strip()
        status = self.status_combo.currentText()
        if status: params['status'] = status
        t = self.type_map.get(self.type_search.currentText(), '')
        if t: params['card_type'] = t
        return params

    def load_list(self):
        params = self.build_params()
        try:
            resp = requests.get(f"{API_URL}/list", params=params, timeout=5)
            result = resp.json()
            if result.get('success'):
                cards = result.get('cards', [])
                self.total_pages = result.get('pages', 1)
                total = result.get('total', 0)
                self.total_lbl.setText(f'总数: {total}')
                self.page_lbl.setText(f'第{self.current_page}/{self.total_pages}页')
                self.table.setRowCount(len(cards))
                for i, card in enumerate(cards):
                    self.table.setItem(i, 0, QTableWidgetItem(card['card_key']))
                    self.table.setItem(i, 1, QTableWidgetItem(self.type_map_rev.get(card['card_type'], '')))
                    self.table.setItem(i, 2, QTableWidgetItem(card['status']))
                    self.table.setItem(i, 3, QTableWidgetItem(card['generate_time']))
                    self.table.setItem(i, 4, QTableWidgetItem(card.get('activate_time') or ''))
                    self.table.setItem(i, 5, QTableWidgetItem(card.get('expire_time') or ''))
                    self.table.setItem(i, 6, QTableWidgetItem(str(card.get('used_count', 0))))
                    self.table.setItem(i, 7, QTableWidgetItem(str(card.get('max_uses', 0))))
            else:
                QMessageBox.warning(self, '错误', result.get('message', '获取列表失败'))
        except RequestException:
            QMessageBox.critical(self, '网络异常', '网络异常，请检查网络连接。')
        except Exception as e:
            QMessageBox.critical(self, '异常', str(e))

    def on_search(self):
        self.current_page = 1
        self.load_list()

    def prev_page(self):
        if self.current_page > 1:
            self.current_page -= 1
            self.load_list()

    def next_page(self):
        if self.current_page < self.total_pages:
            self.current_page += 1
            self.load_list()

    def on_tab_changed(self, index):
        if self.sender().tabText(index) == '卡密列表':
            self.load_list()

    def delete_selected(self):
        selected = self.table.selectionModel().selectedRows()
        if not selected:
            QMessageBox.information(self, '提示', '未选择任何卡密')
            return
        for idx in selected:
            key = self.table.item(idx.row(), 0).text()
            try:
                requests.post(f"{API_URL}/delete", json={'card_key': key}, timeout=5)
            except RequestException:
                QMessageBox.critical(self, '网络异常', '删除时网络异常，请检查网络。')
                return
        QMessageBox.information(self, '成功', '删除成功')
        self.load_list()

    def show_cell_detail(self, row, column):
        text = self.table.item(row, column).text()
        dlg = QMessageBox(self)
        dlg.setWindowTitle('内容详情')
        dlg.setTextInteractionFlags(Qt.TextSelectableByMouse)
        dlg.setText(text)
        dlg.setStandardButtons(QMessageBox.Ok)
        dlg.exec_()

    def activate_selected(self):
        selected = self.table.selectionModel().selectedRows()
        if not selected:
            QMessageBox.information(self, '提示', '未选择任何卡密')
            return
        for idx in selected:
            key = self.table.item(idx.row(), 0).text()
            try:
                resp = requests.post(f"{API_URL}/activate", json={'card_key': key}, timeout=5)
                result = resp.json()
                if result.get('success'):
                    continue
                else:
                    QMessageBox.critical(self, '激活失败', result.get('message'))
                    return
            except RequestException:
                QMessageBox.critical(self, '网络异常', '激活时网络异常，请检查网络。')
                return

        QMessageBox.information(self, '成功', '激活成功')
        self.load_list()


if __name__ == '__main__':
    try:
        app = QApplication(sys.argv)
        window = CardKeyClient()
        window.show()
        sys.exit(app.exec_())
    except Exception as e:
        QMessageBox.critical(None, '启动失败', f'应用启动失败：{e}')
        sys.exit(1)
